﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;

namespace ZombieMonkeys.Vibria.Logic
{
    public class PuzzleAssembler
    {
        List<Square> tempSquares;
        List<Square> assembledSquares;
        List<int> tempList = new List<int>();
        string difficulty;

        /// <summary>
        /// Constructor for the puzzle
        /// </summary>
        public PuzzleAssembler()
        {

        }

        /// <summary>
        /// Assemble a new puzzle object
        /// </summary>
        /// <param name="rows">the number of rows that the puzzle will contain</param>
        /// <param name="columns">the number columns that the puzzle will contain</param>
        /// <param name="minigrids">the number of minigrids that the puzzle will contain</param>
        /// <returns>A Puzzle for you to solve, sudoku style!</returns>
        public Puzzle Assemble(int rows, int columns, int minigrids, string difficulty)
        {
            int puzzleRows = rows;
            int puzzleCols = columns;
            this.difficulty = difficulty;

            assembledSquares = new List<Square>();

            assembledSquares = buildSquares(puzzleRows, puzzleCols, minigrids);

            Puzzle assembledPuzzle;
            //create the grid from the List<Square> squares
            Grid assembledGrid = new Grid(assembledSquares);
            //create the puzzle from the grid;
            assembledPuzzle = new Puzzle(assembledGrid);
            //create the values for the squares in the grid

            return assembledPuzzle;
        }

        /// <summary>
        /// build the number of squares based on the rows and cols desired
        /// </summary>
        /// <param name="rows">the number of rows for the puzzle</param>
        /// <param name="columns">the number of columns for the puzzle</param>
        /// <returns> a list of row, col assigned squares</returns>
        private List<Square> buildSquares(int rows, int columns, int miniGrids)
        {
            Square tempSquare;
            tempSquares = new List<Square>();

            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < columns; j++)
                {
                    int g = 3 * (j / 3) + i / 3;
                    tempSquare = new Square();

                    tempSquare.SetRow(i);
                    tempSquare.SetColumn(j);
                    tempSquare.SetGrid(g);
                    tempSquare.SetPoint();
                    tempSquares.Add(tempSquare);
                }
            }
            int minToRemove=0;
            int maxToRemove=0;

            if (difficulty != "Solve")
            {
                PuzzleSolver puzzleSolver = new PuzzleSolver(tempSquares);
                if (difficulty == "Easy")
                {
                    minToRemove = 35;
                    maxToRemove = 40;
                }
                if (difficulty == "Hard")
                {
                    minToRemove = 46;
                    maxToRemove = 49;
                }
                if (difficulty == "Moderate")
                {
                    minToRemove = 41;
                    maxToRemove = 45;

                }
                if (difficulty == "Super Hard")
                {
                    minToRemove = 50;
                    maxToRemove = 53;
                }
                puzzleSolver.PuzzleGenerator();
                tempSquares = puzzleSolver.ReturnSquares();
                createEmptySquares(minToRemove, maxToRemove, rows, columns, miniGrids, tempSquares);
            }
            
            return tempSquares;
        }

        private int getEmptyCellCount(List<Square> squares)
        {
            int emptyCount=0;

            //figure out which squares to remove data from, but at this point we have generated a valid solution
            for (int i = 0; i < squares.Count-1; i++)
            {
                if (squares[i].Value == 0)
                {
                    emptyCount += 1;
                }
            }
            
            return emptyCount;

        }

        /// <summary>
        /// a private method for removing squares based on the difficulty
        /// </summary>
        /// <param name="minToRemove">the minimum number of squares to remove</param>
        /// <param name="maxToRemove">the maximum number of squares to remove</param>
        /// <param name="numRows">the number of rows in the puzzle</param>
        /// <param name="numCols">the number of cols in the puzzle</param>
        /// <param name="miniGrids">the number of minigrids in the puzzle</param>
        /// <param name="squares">the squares to evaluate</param>
        private void createEmptySquares(int minToRemove, int maxToRemove, int numRows, int numCols, int miniGrids, List<Square> squares)
        {
            int currentEmptyCount = 0;

            //int cellRow;
            //int cellCol;

            int randRow;
            int randCol;

            while (currentEmptyCount < maxToRemove || currentEmptyCount < minToRemove)
            {
                currentEmptyCount = getEmptyCellCount(squares);
                //find a random cell 
                Random randomToRemove = new Random();

                randRow = randomToRemove.Next(0, numRows);
                randCol = randomToRemove.Next(0, numCols);

                Point pointToRemove = new Point(randRow, randCol);

                emptyCells(minToRemove, maxToRemove, pointToRemove, squares);
            }

        }

        private List<Square> emptyCells(int min, int max, Point point,  List<Square> squares)
        {
            foreach (Square s in squares)
            {
                if (s.GetRow() == point.X && s.GetColumn() == point.Y)
                {
                    s.SetValue(0);
                }
            }

            return squares;
        }

        private void emptyACell(Square squareToEmpty, int squareRow, int squareCol)
        {
            squareToEmpty.SetValue(0);
        }

        //not used
        private MiniGrid createMiniGrid(int rows, int cols)
        {
            MiniGrid tempMiniGrid = new MiniGrid(rows, cols);

            return tempMiniGrid;
        }
    }
}
